package com.boarsoft.boar.message.action;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.boar.message.adapter.MessageBrokerAdapter;
import com.boarsoft.boar.message.biz.RecipientQueueBiz;
import com.boarsoft.boar.message.entity.RecipientQueueEntity;
import com.boarsoft.boar.message.service.QueueMonitor;
import com.boarsoft.common.Authorized;
import com.boarsoft.common.Util;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.message.bean.MessageQueueStat;
import com.boarsoft.message.bean.TargetQueueInfo;

@RestController
@RequestMapping("/recipient/queue")
public class RecipientQueueAction {
	private static final Logger log = LoggerFactory.getLogger(RecipientQueueAction.class);

	@Autowired
	private MessageBrokerAdapter brokerAdapter;

	@Autowired
	private QueueMonitor recipientQueueMonitor;

	@Autowired
	private RecipientQueueBiz recipientQueueBiz;

	@RequestMapping("/stat.do")
	public ReplyInfo<Object> stat(String id) {
		String broker =	recipientQueueBiz.get(id).getBroker();
		MessageQueueStat so = recipientQueueMonitor.getStat(broker, id);
		return new ReplyInfo<Object>(true, so);
	}

	@RequestMapping("/list.do")
	@Authorized(code = "message.recipient.queue.list")
	public ReplyInfo<Object> list(String key, String catalog, String orderBy, int pageNo, int pageSize) {
		PagedResult<RecipientQueueEntity> pr = recipientQueueBiz.list(catalog, key, orderBy, pageNo, pageSize);
		return new ReplyInfo<Object>(true, pr);
	}

	/**
	 * 删除队列信息
	 * 
	 * @param id
	 *            信息id
	 */
	@RequestMapping("/delete.do")
	@Authorized(code = "message.recipient.queue.delete")
	public ReplyInfo<Object> delete(String broker, String id) {
		brokerAdapter.getMessageBroker(broker).removeRecipientQueue(id, false);
		recipientQueueBiz.delete(id);
		return ReplyInfo.SUCCESS;
	}

	// 监控操作
	@RequestMapping("/stop.do")
	@Authorized(code = "message.recipient.queue.stop")
	public ReplyInfo<Object> stop(String id, String code) {
		Vector<String> tm = recipientQueueMonitor.getMoningSet();
		RecipientQueueEntity o = recipientQueueBiz.get(id);
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		tm.remove(code);
		o.setStatus(RecipientQueueEntity.STATUS_ENABLE);
		return ReplyInfo.SUCCESS;
	}

	@RequestMapping("/start.do")
	@Authorized(code = "message.recipient.queue.start")
	public ReplyInfo<Object> start(String id, String code) {
		Vector<String> tm = recipientQueueMonitor.getMoningSet();
		RecipientQueueEntity o = recipientQueueBiz.get(id);
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		tm.add(code);
		o.setStatus(RecipientQueueEntity.STATUS_MONING);
		return ReplyInfo.SUCCESS;
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/enable.do")
	@Authorized(code = "message.recipient.queue.enable")
	public ReplyInfo<Object> enable(String broker,String id) {
		log.warn("Enable recipient queue {}", id);
		RecipientQueueEntity o = recipientQueueBiz.get(id);
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		Map<String, Object> rm = null;
		try {
			rm = (Map<String, Object>) brokerAdapter.getMessageBroker(broker).activeRecipientQueue(o.getCode());
		} catch (Throwable e) {
			log.error("Error on active recipient queue {}", o.getCode(), e);
			return Constants.REPLY_ERROR_INTERNAL;
		}
		if (dealBroadcastResult(rm, o, "active")) {
			o.setStatus(RecipientQueueEntity.STATUS_ENABLE);
			recipientQueueBiz.update(o);
			return ReplyInfo.SUCCESS;
		}
		return new ReplyInfo<Object>(rm);
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/disable.do")
	@Authorized(code = "message.recipient.queue.disable")
	public ReplyInfo<Object> disable(String broker,String id) {
		log.warn("Enable recipient queue {}", id);
		RecipientQueueEntity o = recipientQueueBiz.get(id);
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		Map<String, Object> rm = null;
		try {
			rm = (Map<String, Object>) brokerAdapter.getMessageBroker(broker).deactiveRecipientQueue(o.getCode());
		} catch (Throwable e) {
			log.error("Error on add recipient queue {}", o.getCode(), e);
			return Constants.REPLY_ERROR_INTERNAL;
		}
		if (dealBroadcastResult(rm, o, "deactive")) {
			o.setStatus(RecipientQueueEntity.STATUS_DISABLE);
			recipientQueueBiz.update(o);
			return ReplyInfo.SUCCESS;
		}
		return new ReplyInfo<Object>(rm);
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/save.do")
	@Authorized(code = "message.recipient.queue.save")
	public ReplyInfo<Object> save(String broker, RecipientQueueEntity o) {
		log.warn("Save recipient queue {}", o.getId());
		o.setStatus(TargetQueueInfo.STATUS_ENABLE);
		recipientQueueBiz.save(o);
		Map<String, Object> rm = null;
		if (Util.strIsEmpty(o.getId())) {
			try {
				rm = (Map<String, Object>) brokerAdapter.getMessageBroker(broker).addTargetQueue(o.getCode(), o.getXml());
			} catch (Throwable e) {
				log.error("Error on add recipient queue {}:\n{}\n", //
						o.getCode(), o.getXml(), e);
				return Constants.REPLY_ERROR_INTERNAL;
			}
			if (dealBroadcastResult(rm, o, "add")) {
				return ReplyInfo.SUCCESS;
			}
		} else {
			try {
				rm = (Map<String, Object>) brokerAdapter.getMessageBroker(broker).updateRecipientQueue(o.getCode(), o.getXml());
			} catch (Throwable e) {
				log.error("Error on update recipient queue {}:\n{}\n", //
						o.getCode(), o.getXml(), e);
				return Constants.REPLY_ERROR_INTERNAL;
			}
			if (dealBroadcastResult(rm, o, "update")) {
				return ReplyInfo.SUCCESS;
			}
		}
		return new ReplyInfo<Object>(rm);
	}

	@SuppressWarnings("unchecked")
	@RequestMapping("/remove.do")
	@Authorized(code = "message.recipient.queue.remove")
	public ReplyInfo<Object> remove(String broker, String id, boolean force) {
		log.warn("Remove recipient queue {}, force={}", id, force);
		RecipientQueueEntity o = recipientQueueBiz.get(id);
		if (o == null) {
			return Constants.REPLY_ERROR_NOTFOUND;
		}
		Map<String, Object> rm = null;
		try {
			rm = (Map<String, Object>) brokerAdapter.getMessageBroker(broker).removeRecipientQueue(o.getCode(), force);
		} catch (Throwable e) {
			log.error("Error on remove recipient queue {}", o.getCode(), e);
			return Constants.REPLY_ERROR_INTERNAL;
		}
		if (dealBroadcastResult(rm, o, "remove")) {
			recipientQueueBiz.delete(id);
			return ReplyInfo.SUCCESS;
		}
		return new ReplyInfo<Object>(rm);
	}
	
	@SuppressWarnings("unchecked")
	protected boolean dealBroadcastResult(Map<String, Object> rm, RecipientQueueEntity o, String act){
		if (rm == null || rm.isEmpty()) {
			log.warn("No message server to {} recipient queue {}", act, o.getCode());
			return true;
		}
		boolean flag = true;
		for (Entry<String, Object> en : rm.entrySet()) {
			String k = en.getKey();
			Object x = en.getValue();
			if (x == null) {
				log.error("When {} recipient queue {}, {} return null", act, o.getCode(), k);
				flag = false;
				continue;
			}
			if (x instanceof Exception) {
				log.error("When {} recipient queue {}, {} throw exception", act, o.getCode(), k, x);
				flag = false;
				continue;
			}
			if (x instanceof ReplyInfo) {
				ReplyInfo<Object> r = (ReplyInfo<Object>) x;
				flag = flag && r.isSuccess();
				if (r.isSuccess()) {
					log.info("When {} recipient queue {}, {} successfully", act, o.getCode(), k);
				} else {
					log.error("When {} recipient queue {}, {} failed, {}", act, o.getCode(), k, r.getData());
				}
			}
		}
		return flag;
	}
}